package com.demo2.todo.service.impl;

import com.demo2.todo.model.dto.AuthRequest;
import com.demo2.todo.model.dto.AuthResponse;
import com.demo2.todo.exception.BadRequestException;
import com.demo2.todo.exception.ResourceNotFoundException;
import com.demo2.todo.model.entity.User;
import com.demo2.todo.repository.UserRepository;
import com.demo2.todo.security.JwtTokenProvider;
import com.demo2.todo.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author evi
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;
    private final AuthenticationManager authenticationManager;
    private final JwtTokenProvider jwtTokenProvider;

    @Override
    @Transactional
    public AuthResponse register(AuthRequest request) {
        // 检查用户名是否已存在
        if (userRepository.existsByUsername(request.getUsername())) {
            throw new BadRequestException("用户名已被使用");
        }

        // 创建新用户
        User user = new User();
        user.setUsername(request.getUsername());
        user.setPassword(passwordEncoder.encode(request.getPassword()));
        user.setEnabled(true);
        user.setRole("USER");

        // 保存用户
        User savedUser = userRepository.save(user);

        // 判断是否为管理员（通常注册默认不是管理员，这里仅为示例）
        boolean isAdmin = false;

        // 生成JWT令牌
        String accessToken = jwtTokenProvider.generateAccessToken(savedUser);
        String refreshToken = jwtTokenProvider.generateRefreshToken(savedUser);

        return AuthResponse.builder()
                .id(savedUser.getId())
                .username(savedUser.getUsername())
                .accessToken(accessToken)
                .refreshToken(refreshToken)
                .isAdmin(isAdmin)
                .build();
    }

    @Override
    public AuthResponse login(AuthRequest request) {
        // 认证用户
        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(
                        request.getUsername(),
                        request.getPassword()
                )
        );

        // 设置认证上下文
        SecurityContextHolder.getContext().setAuthentication(authentication);

        // 获取用户详情
        User user = (User) authentication.getPrincipal();

        // 判断是否为管理员
        boolean isAdmin = "ADMIN".equals(user.getRole());
        // 生成JWT令牌
        String accessToken = jwtTokenProvider.generateAccessToken(user);
        String refreshToken = jwtTokenProvider.generateRefreshToken(user);

        return AuthResponse.builder()
                .id(user.getId())
                .username(user.getUsername())
                .accessToken(accessToken)
                .refreshToken(refreshToken)
                .isAdmin(isAdmin)
                .build();
    }

    @Override
    @Transactional(readOnly = true)
    public User getCurrentUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        if (authentication == null || !authentication.isAuthenticated()) {
            throw new ResourceNotFoundException("未找到认证用户");
        }

        String username = authentication.getName();
        return userRepository.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("用户未找到: " + username));
    }


    @Transactional(readOnly = true)
    @Override
    public User getUserById(Long id) {
        return userRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("用户未找到，ID: " + id));
    }

    @Transactional
    @Override
    public void updateUserPassword(Long userId, String newPassword) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new ResourceNotFoundException("用户未找到，ID: " + userId));

        user.setPassword(passwordEncoder.encode(newPassword));
        userRepository.save(user);
    }

    @Transactional
    @Override
    public void disableUser(Long userId) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new ResourceNotFoundException("用户未找到，ID: " + userId));

        user.setEnabled(false);
        userRepository.save(user);
    }

    @Override
    @Transactional
    public User toggleBlacklist(Long userId) {
        // 1. 查询用户是否存在
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new ResourceNotFoundException("用户不存在，ID: " + userId));

        // 2. 检查是否是管理员（禁止拉黑管理员）
        boolean isAdmin = "ADMIN".equals(user.getRole());
        if (isAdmin) {
            throw new SecurityException("不能拉黑管理员用户");
        }

        // 3. 切换拉黑状态（accountNonLocked=false表示被拉黑）
        user.setEnabled(!user.isEnabled());

        // 4. 保存并返回更新后的用户
        return userRepository.save(user);
    }

    @Override
    @Transactional(readOnly = true)
    public User getCurrentUserEntity() {
        // 1. 从安全上下文中获取认证信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        // 2. 检查认证是否有效且不是匿名用户
        if (authentication == null || !authentication.isAuthenticated() ||
                authentication.getPrincipal() instanceof String && "anonymousUser".equals(authentication.getPrincipal())) {
            throw new AccessDeniedException("请先登录");

        }

        // 3. 获取用户名
        String username;
        if (authentication.getPrincipal() instanceof User) {
            // 如果直接是User对象
            return (User) authentication.getPrincipal();
        } else if (authentication.getPrincipal() instanceof UserDetails) {
            // 如果是UserDetails对象
            username = ((UserDetails) authentication.getPrincipal()).getUsername();
        } else if (authentication.getPrincipal() instanceof String) {
            // 字符串类型的用户名
            username = (String) authentication.getPrincipal();
        } else {
            throw new AccessDeniedException("无法获取用户信息");
        }

        // 4. 从数据库查询完整用户实体
        return userRepository.findByUsername(username)
                .orElseThrow(() -> new ResourceNotFoundException("用户未找到: " + username));
    }

    @Transactional
    @Override
    public void blockUser(Long userId) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new ResourceNotFoundException("用户未找到"));

        user.setEnabled(false);
        userRepository.save(user);
    }

    @Transactional
    @Override
    public void unblockUser(Long userId) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new ResourceNotFoundException("用户未找到"));

        user.setEnabled(true);
        userRepository.save(user);
    }

    @Transactional(readOnly = true)
    @Override
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }
}